package com.cblz.bd.server.core.service.impl;

import cn.dev33.satoken.stp.StpInterface;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cblz.bd.common.core.constant.BdAdminConstant;
import com.cblz.bd.common.core.entity.BaAdminGroup;
import com.cblz.bd.common.core.entity.BaMenuRule;
import com.cblz.bd.common.core.exception.BdAdminException;
import com.cblz.bd.redis.spring.boot.starter.service.RedisService;
import com.cblz.bd.server.core.service.BaAdminGroupService;
import com.cblz.bd.server.core.service.BaMenuRuleService;
import com.cblz.bd.server.frontend.entity.BaUser;
import com.cblz.bd.server.frontend.entity.BaUserGroup;
import com.cblz.bd.server.frontend.entity.BaUserRule;
import com.cblz.bd.server.frontend.service.BaUserGroupService;
import com.cblz.bd.server.frontend.service.BaUserRuleService;
import com.cblz.bd.server.frontend.service.BaUserService;
import io.vavr.control.Option;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * {@code @Name:} StpInterfaceImpl
 * {@code @Description: } 自定义权限接口
 * {@code @Author:} by yanjieping
 * {@code @CreateDate:} 2022/11/9 - 周三
 */
@Service
@RequiredArgsConstructor
public class StpInterfaceImpl implements StpInterface {

    private final BaAdminGroupService baAdminGroupService;
    private final BaMenuRuleService baMenuRuleService;
    private final BaUserService baUserService;
    private final BaUserRuleService baUserRuleService;
    private final BaUserGroupService baUserGroupService;
    private final RedisService redisService;

    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        /*
        后台管理端权限
         */
        if (StringUtils.equals(loginType, "login")) {
            String rulesByLoginId = Option.of(baAdminGroupService.getBdAdminRulesByLoginId(Integer.valueOf(loginId.toString()))).getOrNull().stream().map(BaAdminGroup::getRules).toList().stream().collect(Collectors.joining(BdAdminConstant.SYSTEM_COMMA.getVal()));

            if (StringUtils.isBlank(rulesByLoginId)) return Collections.emptyList();

            if (StringUtils.containsAny(rulesByLoginId, "*")) {
                return Option.of(baMenuRuleService.list()).getOrNull().stream().map(BaMenuRule::getAuthorityIdentify).toList();
            }

            return Option.of(baMenuRuleService.list(new LambdaQueryWrapper<BaMenuRule>().in(BaMenuRule::getId, (Object) rulesByLoginId.split(BdAdminConstant.SYSTEM_COMMA.getVal())))).getOrNull().stream().map(BaMenuRule::getAuthorityIdentify).toList();
        }
        /*
        外部用户管理端权限
         */
        else if (StringUtils.equals(loginType, "user")) {
            BaUser baUser = Option.of(baUserService.getById(loginId.toString())).getOrElseThrow(() -> {
                throw new BdAdminException("未找到ID为「" + loginId + "」的用户");
            });
            BaUserGroup baUserGroup = baUserGroupService.getRulesByUserId(baUser.getGroupId())._1;
            // 如果包含 * 就代表拥有所有菜单权限
            if (StringUtils.containsAny(baUserGroup.getRules(), "*")) {
                return Option.of(baUserRuleService.list(new LambdaQueryWrapper<BaUserRule>().ne(BaUserRule::getId, 1))).getOrNull().stream().map(BaUserRule::getName).toList();
            }

            return Option.of(baUserRuleService.list(new LambdaQueryWrapper<BaUserRule>().in(BaUserRule::getId, baUserGroup.getRules()))).getOrElseThrow(() -> {
                throw new BdAdminException("未找到ID为「" + baUser.getGroupId() + "」的菜单信息");
            }).stream().map(BaUserRule::getName).toList();
        }
        return null;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        if (StringUtils.equals(loginType, "login")) {
            return Option.of(baAdminGroupService.getBdAdminRulesByLoginId(Integer.valueOf(loginId.toString()))).getOrNull().stream().map(BaAdminGroup::getName).toList();
        } else if (StringUtils.equals(loginType, "user")) {
            BaUser baUser = Option.of(baUserService.getById(loginId.toString())).getOrElseThrow(() -> {
                throw new BdAdminException("未找到ID为「" + loginId + "」的用户");
            });
            return List.of(baUserGroupService.getRulesByUserId(baUser.getGroupId())._1.getName());
        }
        return null;
    }

}
